perm filename SIMAUX.SAI[SYS,HE] blob
sn#022302 filedate 1973-01-26 generic text, type T, neo UTF8
COMMENT ⊗ VALID 00019 PAGES
RECORD PAGE DESCRIPTION
00001 00001
00007 00002 ENTRY DUMMY
00011 00003 INTERNAL PROCEDURE READ_FROM_DISK
00015 00004 *** DISK I/O STUFF ***
00016 00005 α *** LINEAR EQUATION SOLVER PROCEDURES FOLLOW. ***
00019 00006 IF BIGGEST=0 THEN
00021 00007 INTERNAL PROCEDURE IMPROVE(INTEGER NSAFE REAL ARRAY A,LU,B,XREFERENCE REAL DIGITS)
00024 00008 α ** NUMBER CRUNCHING ROUTINES ***
00026 00009 INTERNAL PROCEDURE WXFORM(SAFE REAL ARRAY FRUM,TU,TRANS)
00029 00010 INTERNAL PROCEDURE BESTIN(SAFE REAL ARRAY PJ,QJ,PK,QK,INTREFERENCE REAL MISDIS)
00031 00011 INTERNAL PROCEDURE MATMULT(SAFE REAL ARRAY A,B,CINTEGER N)
00032 00012 α *** MISC. HOUSEKEEPING ROUTINES ***
00033 00013 α *** SOME USEFUL PROCEDURES ***
00035 00014 INTERNAL ITEMVAR PROCEDURE NEXTV(SAFE REAL ARRAY ITEMVAR V1,V2)
00037 00015 α *** MORE USEFUL ROUTINES ***
00038 00016 T IS TOP AND B IS BOTTOM IMAGE VERTEX ASSUMED TO LIE
00041 00017 INTERNAL PROCEDURE HORIZ_PLANE_PT(SAFE REAL ARRAY ITEMVAR U,K)
00044 00018 INTERNAL BOOLEAN PROCEDURE PARALLEL(ITEMVAR E1,E2)
00048 00019 INTERNAL PROCEDURE VERT2
00049 ENDMK
⊗;
ENTRY DUMMY;
BEGIN "AUXILIARY SIMPLE PROCEDURES"
REQUIRE 400 PNAMES;
REQUIRE "PREAMB.SAI[SYS,HE]" SOURCE_FILE;
REQUIRE "SAITRG[SYS,HE]" LOAD_MODULE;
REQUIRE "DPDP.REL[SYS,HE]" LOAD_MODULE;
REQUIRE "<>||" DELIMITERS;
EXTERNAL REAL PROCEDURE SQRT(REAL X);
EXTERNAL REAL PROCEDURE ACOS(REAL X);
EXTERNAL REAL PROCEDURE ATAN(REAL X);
COMMENT ***** LOCAL THINGS ***** ;
INTERNAL SAFE REAL ARRAY A,AI[1:3,1:3],LENS[1:3];
COMMENT A AND AI MATRICES FOR THE OBJECT BEING CONSIDERED
AT THE MOMENT -- A IS COLINEATION MATRIX (TABLE → SCREEN)
AND AI ITS INVERSE (SCREEN → TABLE).
BOTH MUST BE POST-MULTIPLIED ;
INTERNAL SAFE REAL ARRAY MCP[1:3];
INTERNAL SAFE REAL ARRAY CTABLE[1:4];
INTERNAL REAL LX,DIGITS,MDP;
INTERNAL ITEMVAR NEXTSYM,TTT;
INTERNAL ITEMVAR Y,L1,L2,L3,LASTL;
INTERNAL SAFE REAL ARRAY ITEMVAR X,V1,V2,V3,V4,VA,VB,B;
INTERNAL SET SES,SVS,S1,VERTEDG;
INTERNAL INTEGER C,ICX,ICY,SPECIAL_VERT,VERT0F;
INTERNAL BOOLEAN BVERT;
DEFINE FILE=<7>,SIBS=<13>,ID=<7>,FIRST1=<8>,SOMETHING=<9>,
SUBR=<SIMPLE PROCEDURE>,
ISUBR=<INTERNAL SIMPLE PROCEDURE>,
IRSUBR=<INTERNAL SIMPLE REAL PROCEDURE>,
IXSUBR=<INTERNAL SIMPLE ITEMVAR PROCEDURE>,
IRXSUBR=<INTERNAL SIMPLE REAL ITEMVAR PROCEDURE>,
ISRAXSUBR=<INTERNAL SIMPLE SAFE REAL ARRAY ITEMVAR PROCEDURE>,
ISSUBR=<INTERNAL SIMPLE STRING PROCEDURE>,
α=<COMMENT>,⊂=<BEGIN>,⊃=<END>,$=<GLOBAL>,∀=<FOREACH>,
WAIT=<>,∂=<DATUM>,
YES=<(INCHWL="Y")>,TYPE=<OUTSTR(>,EOM=<&'12&'15)>,TTY=<1>,
TYPET=<IF TYP_SIMP THEN OUTSTR(>,
TYPED=<IF DEB_SIMP THEN OUTSTR(>,
EOS=<)>,
ADJ(L1,L2)=<((ENDPT⊗L1) ∩ (ENDPT⊗L2) ≠ PHI)>,
GADJ(L1,L2)=<((GLOBAL ENDPT⊗L1) ∩ (GLOBAL ENDPT⊗L2) ≠ PHI)>;
DEFINE LAEQ(A,B)"{}"={ABS(A-B)<0.49};
DEFINE S1U=<STEP 1 UNTIL>,ASSIGN=<FOREACH>,HOLDS=<DO DONE;>,
READ=<INTN(GETS)>,READS(A)=<INTNS(GETS,A)>, READA(A)=<INTNA(GETS,A)>;
DEFINE GETLINE=<1>,
NEXT_LINE=<LINESTR←INPUT(1,GETLINE)>,
IN_INT=<INTSCAN(LINESTR,BREAK)>,
IN_REAL=<REALSCAN(LINESTR,BREAK)>,
INPUT_INTEGER=<INTSCAN(LINESTR←INPUT(1,GETLINE),BREAK)>,
INPUT_REAL=<REALSCAN(LINESTR←INPUT(1,GETLINE),BREAK)>;
INTERNAL PROCEDURE READ_FROM_DISK;
BEGIN "READ IN"
STRING FILEN,LINESTR;
INTEGER BREAK,EOF,FLAG,I,J,K,NUMOBJ,NUMVER,NUMLIN,NUMREG,V#;
SAFE REAL ARRAY SIZE7[1:7],FOURBY4[1:4,1:4],CAMX[1:10,1:3];
REAL ARRAY ITEMVAR XR, V;
OPEN(1,"DSK",0,2,0,120,BREAK,EOF);
SETBREAK(GETLINE,'12,'15,"INS");
DO ⊂ "IO" TYPE "FILE NAME←" EOS; FILEN←INCHWL;
LOOKUP(1,FILEN,FLAG) ⊃ "IO" UNTIL ¬FLAG;
α number of objects in the file;
NUMOBJ←INPUT_INTEGER;
FOR I←1 STEP 1 UNTIL NUMOBJ DO
BEGIN "INPUT AN OBJECT"
α number of vertices for an object;
NUMVER←INPUT_INTEGER;
BEGIN "OBJECT I"
SAFE REAL ARRAY VERTS[1:NUMVER,1:2];
XR←$ NEW(FOURBY4);
PUT XR IN BLOBS;
FOR J←1 STEP 1 UNTIL NUMVER DO
⊂ "VERTICES"
NEXT_LINE; VERTS[J,1]←IN_REAL;
VERTS[J,2]←IN_REAL ⊃ "VERTICES";
α number of lines in the object - ignore;
NUMLIN←INPUT_INTEGER;
FOR J←1 STEP 1 UNTIL NUMLIN DO NEXT_LINE;
α number of regions - just use the first region to get outline;
NUMREG←INPUT_INTEGER;
FOR J←1 STEP 1 UNTIL NUMREG DO
IF J=1
THEN BEGIN "OUTLINE"
SAFE REAL ARRAY LINES[1:2,0:NUMLIN];
NEXT_LINE; IN_INT;
FOR K←1 STEP 1 UNTIL NUMLIN DO
⊂ "TEST" V#←IN_INT;
LINES[1,K]←VERTS[V#,1];
LINES[2,K]←VERTS[V#,2] ⊃ "TEST";
LINES[1,0]←NUMLIN;
$ MAKE BOUNDARY⊗XR ≡ $ NEW(LINES);
END "OUTLINE"
ELSE NEXT_LINE;
α number of dangling lines;
NUMLIN←INPUT_INTEGER;
FOR I←1 STEP 1 UNTIL NUMLIN DO NEXT_LINE;
END "OBJECT I";
END "INPUT AN OBJECT";
α get the camera transform;
NUMLIN←INPUT_INTEGER;
FOR I←1 STEP 1 UNTIL NUMLIN DO
⊂ "T" CAMX[I,1]←INPUT_REAL; CAMX[I,2]←IN_REAL; CAMX[I,3]←IN_REAL ⊃ "T";
∀ XR|XR ε BLOBS DO $ MAKE XFORM⊗XR≡$ NEW(CAMX);
END "READ IN";
COMMENT *** DISK I/O STUFF ***;
COMMENT
THIS IS THE MECHANISM FOR READING IN PROTOTYPES,
HANDLING NEW ITEMS IN THE WORLD;
IXSUBR INTN(STRING S);
⊂ ITEMVAR X; INTEGER I;
X←CVSI (S,I);
IF I THEN ⊂ X←$ NEW; NEW_PNAME (X,S) ⊃;
RETURN(X) ⊃;
IRXSUBR INTNS(STRING S;REAL V);
⊂ REAL ITEMVAR X;
X←INTN(S);
$ ∂(X)←V;
RETURN(X) ⊃;
ISRAXSUBR INTNA(STRING S;SAFE REAL ARRAY A);
⊂ SAFE REAL ARRAY ITEMVAR X; INTEGER I;
X←CVSI(S,I);
IF I THEN ⊂ X←$ NEW(A); NEW_PNAME(X,S) ⊃;
RETURN(X) ⊃;
ISSUBR GETS;
⊂ STRING S;
S←INPUT(FILE,FIRST1); RETURN (INPUT(FILE,ID)) ⊃;
α *** LINEAR EQUATION SOLVER PROCEDURES FOLLOW. ***;
INTERNAL SAFE INTEGER ARRAY PS[1:10];
ISUBR SINGULAR(INTEGER WHY);
α PRINTS ERROR MESSAGES FOR DECOMPOSE AND IMPROVE;
CASE WHY OF
⊂ TYPE "MATRIX WITH ZERO ROW IN DECOMPOSE." EOM;
TYPE "SINGULAR MATRIX IN DECOMPOSE. SOLVE WILL DIVIDE BY ZERO." EOM;
TYPE "NO CONVERGENCE IN IMPROVE. MATRIX IS NEARLY SINGULAR." EOM ⊃;
INTERNAL PROCEDURE DECOMPOSE(INTEGER N;SAFE REAL ARRAY A,LU);
COMMENT A,LU[1:N,1:N];
COMMENT USES GLOBAL SAFE INTEGER ARRAY PS;
COMMENT COMPUTES TRIANGULAR MATRICES L AND U AND PERMUTATION
MATRIX P SO THAT LU=PA. STORES L-I AND U IN LU.
ARRAY PS CONTAINS PERMUTED ROW INDICES;
COMMENT DECOMPOSE(N,A,A) OVERWRITES A WITH LU;
BEGIN
LABEL ENDKLOOP;
SAFE REAL ARRAY SCALES[1:N];
INTEGER I,J,K,PIVOTINDEX;
REAL NORMROW,PIVOT,SIZE,BIGGEST,MULT;
COMMENT INITIALIZE PS,LU AND SCALES;
FOR I←1 STEP 1 UNTIL N DO
BEGIN
PS[I]←I;
NORMROW←0;
FOR J←1 STEP 1 UNTIL N DO
BEGIN
LU[I,J]←A[I,J];
IF (NORMROW<ABS(LU[I,J])) THEN NORMROW←ABS(LU[I,J]);
END;
IF (NORMROW≠0) THEN SCALES[I]←1/NORMROW
ELSE BEGIN SCALES[I]←0; SINGULAR(0); END;
END;
COMMENT GAUSSIAN ELIMINATION WITH PARTIAL PIVOTING;
FOR K←1 STEP 1 UNTIL N-1 DO
BEGIN
BIGGEST←0;
FOR I←K STEP 1 UNTIL N DO
BEGIN
SIZE←ABS(LU[PS[I],K])*SCALES[PS[I]];
IF (BIGGEST<SIZE) THEN
BEGIN BIGGEST←SIZE; PIVOTINDEX←I; END;
END;
IF BIGGEST=0 THEN
BEGIN SINGULAR(1); GO TO ENDKLOOP; END;
IF PIVOTINDEX≠K THEN
BEGIN
J←PS[K];PS[K]←PS[PIVOTINDEX];PS[PIVOTINDEX]←J;
END;
PIVOT←LU[PS[K],K];
FOR I←K+1 STEP 1 UNTIL N DO
BEGIN
LU[PS[I],K]←MULT←(LU[PS[I],K]/PIVOT);
IF MULT ≠0 THEN
FOR J←K+1 STEP 1 UNTIL N DO
LU[PS[I],J]←LU[PS[I],J]-MULT*LU[PS[K],J];
COMMENT INNER LOOP. ONLY COLUMN SUBSCRIPT
VARIES. USE MACHINE CODE IF NECESSARY
FOR EFFICIENCY;
END;
ENDKLOOP:
END;
IF (LU[PS[N],N]=0) THEN SINGULAR(1);
END ;
ISUBR SOLVE(INTEGER N;SAFE REAL ARRAY LU,B,X);
α LU[1:N,1:N],B,X[1:N];
α USES GLOBAL SAFE INTEGER ARRAY PS;
α SOLVES AX=B USING LU FROM DECOMPOSE;
BEGIN
INTEGER I,J;
REAL DOT;
FOR I←1 STEP 1 UNTIL N DO
BEGIN
DOT←0;
FOR J←1 STEP 1 UNTIL I-1 DO
DOT←DOT+LU[PS[I],J]*X[J];
X[I]←B[PS[I]]-DOT;
END;
FOR I←N STEP -1 UNTIL 1 DO
BEGIN
DOT←0;
FOR J←I+1 STEP 1 UNTIL N DO
DOT←DOT+LU[PS[I],J]*X[J];
X[I]←(X[I]-DOT)/LU[PS[I],I];
END;
α AS IN DECOMPOSE, THE INNER LOOPS INVOLVE ONLY THE COLUMN
SUBSCRIPT OF LU AND MAY BE MACHINE CODED FOR EFFICIENCY;
END;
INTERNAL PROCEDURE IMPROVE(INTEGER N;SAFE REAL ARRAY A,LU,B,X;REFERENCE REAL DIGITS);
COMMENT A,LU[1:N,1:N],B,X[1:N];
COMMENT A IS THE ORIGINAL MATRIX, LU IS FROM DECOMPOSE,B IS THE
RIGHT HAND SIDE,X IS THE SOLUTION FROM SOLVE. IMPROVES
X TO MACHINE ACCURACY AND SETS DIGITS TO THE NUMBER
OF DIGITS OF X WHICH DO NOT CHANGE;
COMMENT MACHINE DEPENDENT QUANTITIES INDICATED BY 0-0;
BEGIN
LABEL CONVERGED;
SAFE REAL ARRAY R[1:N],DX[1:N];
INTEGER ITER, ITMAX,I;
REAL T,NORMX,NORMDX,EPS;
FORTRAN REAL PROCEDURE ALOG10;
INTERNAL REAL PROCEDURE ACCUMDOTPROD
(INTEGER N;SAFE REAL ARRAY A;INTEGER I;SAFE REAL ARRAY X;REAL EXTRATERM);
BEGIN
FORTRAN REAL PROCEDURE ADPFOR;
REAL SUM;
COMMENT THIS PROCEDURE SHOULD EVALUATE THE INNER PRODUCT OF
THE I-TH ROW OF ARRAY A WITH THE VECTOR X, THEN
ADD EXTRATERM TO THE RESULT. THE MULTIPLICATION
A[I,J]*X[J] MUST YIELD A DOUBLE PRECISION RESULT
AND ALL THE ADDITIONS MUST BE DONE IN DOUBLE
PRECISION. THE BODY OF THE PROCEDURE CANNOT BE
WRITTEN IN GOGOL;
SUM←ADPFOR(N,A[1,1],I,X[1],EXTRATERM);
RETURN (SUM);
END;
EPS←1.0@-8;
ITMAX←16;
NORMX←0;
FOR I←1 STEP 1 UNTIL N DO
IF (NORMX<ABS(X[I])) THEN NORMX←ABS(X[I]);
IF NORMX=0 THEN
BEGIN DIGITS←-ALOG10(EPS); GO TO CONVERGED END;
FOR ITER ←1 STEP 1 UNTIL ITMAX DO
BEGIN
FOR I←1 STEP 1 UNTIL N DO
R[I]←ACCUMDOTPROD(N,A,I,X,B[I]);
SOLVE(N,LU,R,DX);
NORMDX←0;
FOR I←1 STEP 1 UNTIL N DO
BEGIN
T←X[I];
X[I]←X[I]+DX[I];
IF (NORMDX<ABS(X[I]-T)) THEN NORMDX←ABS(X[I]-T);
END;
IF ITER =1 THEN
DIGITS←-ALOG10(IF (NORMDX≠0)THEN NORMDX/NORMX
ELSE EPS);
IF (NORMDX≤EPS*NORMX) THEN GO TO CONVERGED;
END ;
COMMENT ITERATION DID NOT CONVERGE;
SINGULAR(2);
CONVERGED:
END;
α ** NUMBER CRUNCHING ROUTINES ***;
INTERNAL PROCEDURE INVERT(SAFE REAL ARRAY MAT,INVMAT;INTEGER N);
COMMENT INVERTS A NXN MATRIX;
BEGIN SAFE REAL ARRAY LU[1:N,1:N],IDENTROW,X[1:N];
INTEGER I,J;
DECOMPOSE(N,MAT,LU);
FOR I←1 S1U N DO
BEGIN
FOR J←1 S1U N DO IDENTROW[J]←IF I=J THEN 1.0 ELSE 0.0;
SOLVE(N,LU,IDENTROW,X);
IMPROVE(N,MAT,LU,IDENTROW,X,DIGITS);
FOR J←1 STEP 1 UNTIL N DO INVMAT[J,I]←X[J];
END;
END;
INTERNAL PROCEDURE TRANSPOSE(SAFE REAL ARRAY TO,FROM);
BEGIN "TRANSPOSE"
INTEGER I,J;
SAFE REAL ARRAY TEMP[1:4,1:4];
FOR I←1 S1U 4 DO
FOR J←1 S1U 4 DO
TEMP[J,I]←FROM[I,J];
ARRTRAN(TO,TEMP);
END "TRANSPOSE";
INTERNAL PROCEDURE HOMO_XFRM(SAFE REAL ARRAY P,T);
COMMENT TRANSFORM P BY THE 4X4 HOMOGENEOUS TRANSFORMATION MATRIX T;
BEGIN SAFE REAL ARRAY TEMP[1:4];
INTEGER I,J;
FOR I←1 S1U 4 DO
BEGIN
TEMP[I]←0.0;
FOR J←1 S1U 4 DO
TEMP[I]←TEMP[I]+T[I,J]*P[J];
END;
FOR J←1 S1U 4 DO P[J]←TEMP[J]/TEMP[4];
END;
INTERNAL PROCEDURE WXFORM(SAFE REAL ARRAY FRUM,TU,TRANS);
BEGIN SAFE REAL ARRAY TEMP[1:3];
INTEGER I,J;
FOR I←1 S1U 3 DO
BEGIN
TEMP[I]←0.0;
FOR J←1 S1U 3 DO
TEMP[I]←TEMP[I]+FRUM[J]*TRANS[I,J];
END;
FOR I←1 S1U 3 DO TU[I]←TEMP[I]/TEMP[3];
RETURN;
END;
INTERNAL PROCEDURE IMAGE_POINT(SAFE REAL ARRAY V;REFERENCE INTEGER X,Y);
COMMENT FIND THE IMAGE COORDINATES OF POINT V;
BEGIN REAL VZ,T0,TX,TY,W;
VZ←V[3];
T0←VZ/(VZ-LENS[3]);
TX←LENS[1]*T0+V[1]*(1-T0);
TY←LENS[2]*T0+V[2]*(1-T0);
W←TX*A[3,1]+TY*A[3,2]+A[3,3];
X←(TX*A[1,1]+TY*A[1,2]+A[1,3])/W;
Y←(TX*A[2,1]+TY*A[2,2]+A[2,3])/W;
RETURN;
END;
INTERNAL PROCEDURE IMAGECOR(SAFE REAL ARRAY W;REFERENCE REAL X,Y);
COMMENT FIND THE IMAGE COORDINATES OF POINT W, USING SHY'S PROCEDURE;
BEGIN "IMAGE COOR"
INTEGER I,J,K; REAL AC,DC;SAFE REAL ARRAY V,U[1:3];
AC←LENS[3];DC←W[3]-AC;
V[1]←(LENS[1]*W[3]-AC*W[1])/DC;
V[2]←(LENS[2]*W[3]-AC*W[2])/DC;
V[3]←1;
FOR I←1,2,3 DO BEGIN
AC←0;
FOR J←1,2,3 DO AC←AC+A[I,J]*V[J];
U[I]←AC;
END;
X←U[1]/U[3]; Y←U[2]/U[3];
END "IMAGE COOR";
INTERNAL PROCEDURE TABLECOR(SAFE REAL XI,YI;REFERENCE REAL XT,YT);
COMMENT TRANSFORM IMAGE COORDS TO TABLE TOP COORDS;
BEGIN "TABLECOR"
INTEGER I,J,K; REAL AC; SAFE REAL ARRAY V,U[1:3];
V[1]←XI; V[2]←YI; V[3]←1;
FOR I←1 ,2,3 DO BEGIN
AC←0;
FOR J←1,2,3 DO AC←AC+AI[I,J]*V[J];
U[I]←AC;
END;
XT←U[1]/U[3];
YT←U[2]/U[3];
END "TABLECOR";
INTERNAL PROCEDURE BESTIN(SAFE REAL ARRAY PJ,QJ,PK,QK,INT;REFERENCE REAL MISDIS);
COMMENT FINDS THE "BEST INTERSECTION" OF 2 SKEW LINES;
BEGIN SAFE REAL ARRAY VJ[1:3],VK[1:3],DIS[1:3],PD[1:3];
REAL A,B,C,D,E,DET,TJ,TK; INTEGER I;
A←B←C←D←E←MISDIS←0;
FOR I←1 STEP 1 UNTIL 3 DO
BEGIN
PD[I]←PK[I]-PJ[I];
VJ[I]←QJ[I]-PJ[I];
VK[I]←QK[I]-PK[I];
A←A+VJ[I]↑2;
B←B-VJ[I]*VK[I];
C←C+VK[I]↑2;
D←D+PD[I]*VJ[I];
E←E-PD[I]*VK[I];
END;
DET←A*C-B↑2;
TJ←(C*D-B*E)/DET;
TK←(A*E-B*D)/DET;
FOR I←1 STEP 1 UNTIL 3 DO
BEGIN
INT[I]←(PJ[I]+PK[I]+TK*VK[I]+TJ*VJ[I])/2;
DIS[I]←TJ*VJ[I]-TK*VK[I]-PD[I];
MISDIS←MISDIS+DIS[I]↑2;
END;
MISDIS←SQRT(MISDIS);
RETURN;
END;
INTERNAL PROCEDURE MATMULT(SAFE REAL ARRAY A,B,C;INTEGER N);
BEGIN
COMMENT MULTIPLIES 2 NXN MATRICES;
INTEGER I,J,K; REAL SUM;
SAFE REAL ARRAY D[1:N,1:N];
FOR I←1 STEP 1 UNTIL N DO
FOR J←1 STEP 1 UNTIL N DO
BEGIN
SUM←0.0;
FOR K←1 STEP 1 UNTIL N DO
SUM←SUM+A[I,K]*B[K,J];
D[I,J]←SUM;
END;
ARRTRAN(C,D);
RETURN;
END;
α *** MISC. HOUSEKEEPING ROUTINES ***;
INTERNAL STRING PROCEDURE PRINTNAME(ITEMVAR X);
BEGIN INTEGER I, J, K, N;
STRING SI;
N←CVN(X);
GETFORMAT(J,K);
SETFORMAT(0,0);
SI←CVIS(X,I);
IF I THEN SI←IF N>1025 THEN "G"&CVOS(N) ELSE "L"&CVOS(N);
SETFORMAT(J,K);
RETURN(SI);
END;
INTERNAL STRING PROCEDURE GENSYM (ITEMVAR X);
BEGIN STRING S;
INTEGER ITEMVAR Y;
LABEL L1;
S←PRINTNAME(X);
FOREACH Y | NEXTSYM ⊗ X ≡ Y DO GO TO L1;
Y←NEW(0);
MAKE NEXTSYM ⊗ X ≡ Y;
L1: DATUM(Y)←DATUM(Y)+1;
SETFORMAT(0,0);
S←S&CVS(DATUM(Y));
SETFORMAT (10,6);
RETURN (S);
END;
α *** SOME USEFUL PROCEDURES ***;
INTERNAL BOOLEAN PROCEDURE VERT(ITEMVAR E);
COMMENT IS EDGE E APPROX VERTICAL IN THE PROJECTION?;
BEGIN
SAFE REAL ARRAY ITEMVAR P1,P2;
SET ES; REAL VERLEN,VERTOL;
ES←(ENDPT⊗E);
P1←LOP(ES);
P2←COP(ES);
VERLEN←ABS(DATUM(P1)[6]-DATUM(P2)[6]);
VERTOL←VERLEN/(IF C=5 THEN 5.0 ELSE 4.0);
RETURN(ABS(DATUM(P1)[5]-DATUM(P2)[5])<VERTOL);
END;
INTERNAL REAL PROCEDURE LENTH(ITEMVAR L);
COMMENT RETURNS THE ACTUAL LENGTH OF EDGE L;
BEGIN
SET S;
SAFE REAL ARRAY ITEMVAR U,V;
REAL LENTHG;
S←(ENDPT⊗L);
U←LOP(S);
V←COP(S);
LENTHG←(DATUM(U)[1]-DATUM(V)[1])↑2+
(DATUM(U)[2]-DATUM(V)[2])↑2+(DATUM(U)[3]-DATUM(V)[3])↑2;
LENTHG←SQRT(LENTHG);
TYPET "LENTH - LENGTH FOR "&PRINTNAME(L)&"="&CVG(LENTHG) EOM;
RETURN (LENTHG);
END;
INTERNAL REAL PROCEDURE GLENTH(ITEMVAR L);
COMMENT RETURNS THE ACTUAL LENGTH OF EDGE L;
BEGIN
SET S;
SAFE REAL ARRAY ITEMVAR U,V;
S←(GLOBAL ENDPT⊗L);
U←LOP(S);
V←COP(S);
RETURN(SQRT((GLOBAL DATUM(U)[1]-GLOBAL DATUM(V)[1])↑2+
(GLOBAL DATUM(U)[2]-GLOBAL DATUM(V)[2])↑2
+(GLOBAL DATUM(U)[3]-GLOBAL DATUM(V)[3])↑2));
END;
INTERNAL ITEMVAR PROCEDURE NEXTV(SAFE REAL ARRAY ITEMVAR V1,V2);
COMMENT RETURNS NEXT VERTEX IN RING (GOING FROM V1 TO V2);
BEGIN
SET S;
SAFE REAL ARRAY ITEMVAR X,Y;
IF DEB_SIMP
THEN BEGIN TYPE "NEXTV "& PRINTNAME(V1)&" "&PRINTNAME(V2) EOM; WAIT END;
FOREACH LASTL | ENDPT⊗LASTL≡V2 DO
BEGIN
S←(ENDPT⊗LASTL);
IF S∩{V1}=PHI THEN
BEGIN
X←LOP(S);
Y←COP(S);
IF X=V2 THEN RETURN (Y) ELSE RETURN (X);
END;
END;
TYPE "NEXTV SCREWUP " EOM;
END;
ISUBR CROSS_PROD(SAFE REAL ARRAY A,B,CP);
α RETRUNS AXB IN CP;
⊂ CP[1]←A[2]*B[3]-A[3]*B[2];
CP[2]←A[3]*B[1]-A[1]*B[3];
CP[3]←A[1]*B[2]-A[2]*B[1] ⊃;
α *** MORE USEFUL ROUTINES ***;
INTERNAL ITEMVAR PROCEDURE HIGHEST(SET S);
COMMENT S IS A SET OF IMAGE VERTICES- RETURNS THE "HIGHEST";
BEGIN
SAFE REAL ARRAY ITEMVAR X,Y;
Y←COP(S);
FOREACH X|XεS DO IF DATUM(X)[6]<DATUM(Y)[6] THEN Y←X;
RETURN(Y);
END;
INTERNAL ITEMVAR PROCEDURE LOWEST(SET S);
COMMENT S IS A SET OF IMAGE VERTICES - RETURNS THE "LOWEST";
BEGIN
SAFE REAL ARRAY ITEMVAR X,Y;
Y←COP(S);
FOREACH X| XεS DO IF DATUM(X)[6]>DATUM(Y)[6] THEN Y←X;
RETURN(Y);
END;
COMMENT T IS TOP AND B IS BOTTOM IMAGE VERTEX ASSUMED TO LIE
ON A LINE NORMAL TO THE TABLE PLANE.
RETURNS WITH THE TRUE 3-D COORDS STUFFED INTO T;
INTERNAL PROCEDURE VERT_LINE_PT(SAFE REAL ARRAY ITEMVAR T,B);
BEGIN OWN SAFE REAL ARRAY TOP,INT,P,BASE[1:3];
INTEGER I;
REAL MISDIS;
∂(T)[3]←(-LENS[3]*(∂(B)[1]-LENS[1])/(∂(T)[1]-LENS[1])) + LENS[3];
∂(T)[1]←∂(B)[1];
∂(T)[2]←∂(B)[2];
COMMENT FOR I←1 S1U 2 DO
BEGIN
TOP[I]←DATUM(T)[I];
COMMENT P[I]←BASE[I]←DATUM(B)[I];
COMMENT END;
COMMENT TOP[3]←BASE[3]←0.0;
COMMENT P[3]←1.0;
COMMENT BESTIN(TOP,LENS,BASE,P,INT,MISDIS);
COMMENT FOR I← 1 S1U 3 DO DATUM(T)[I]←INT[I];
if deb_simp
then begin
type "CALL TO VERT_LINE_PT. "&'12&'15&
" TOP IS "&PRINTNAME(T)&", BOTTOM IS "&PRINTNAME(B) eom;
wait;
end;
END;
INTERNAL PROCEDURE VERT_PLANE_PT(SAFE REAL ARRAY ITEMVAR T,B1,B2);
COMMENT T,B1,B2 ARE IMAGE VERTICES.
T LIES OFF THE TABLE IN A PLANE NORMAL TO THE
THE TABLE WHICH PASSES THRU B1 AND B2.
RETURNS WITH 3-D COORDS STUFFED IN T;
BEGIN
REAL M,B,DX,T1,XT,YT;
DX←DATUM(B2)[1]-DATUM(B1)[1];
M←(DATUM(B2)[2]-DATUM(B1)[2])/DX;
B←(DATUM(B2)[1]*DATUM(B1)[2]-DATUM(B1)[1]*DATUM(B2)[2])/DX;
XT←DATUM(T)[1];
YT←DATUM(T)[2];
T1←(M*XT-YT+B)/(LENS[2]-YT-M*(LENS[1]-XT));
DATUM(T)[1]←T1*LENS[1]+(1.0-T1)*XT;
DATUM(T)[2]←T1*LENS[2]+(1.0-T1)*YT;
DATUM(T)[3]←T1*LENS[3];
if deb_simp
then begin
type "CALL TO VERT_PLANE_PT. "&'12&'15&
" PLANE EDGE:"&PRINTNAME(B1)&","&PRINTNAME(B2)&
" VERTEX:"&PRINTNAME(T) EOM;
wait;
end;
END;
INTERNAL PROCEDURE HORIZ_PLANE_PT(SAFE REAL ARRAY ITEMVAR U,K);
COMMENT U IS AN UNKNOWN IMAGE POINT LYING IN THE SAME PLANE PARALLEL TO
THE TABLE AS K ,A POINT WHOSE 3-D COORDS ARE KNOWN.
RETURNS WITH 3-D COORDS OF U PROPERLY STUFFED IN.;
BEGIN
REAL H,HZC;
H←DATUM(K)[3];
HZC←H/LENS[3];
DATUM(U)[1]←HZC*LENS[1]+DATUM(U)[1]*(1.0-HZC);
DATUM(U)[2]←HZC*LENS[2]+DATUM(U)[2]*(1.0-HZC);
DATUM(U)[3]←H;
if deb_simp
then begin
type "CALL TO HORIZ_PLANE_PT. "&'12&'15&
" UNKNOWN VERTEX:"&PRINTNAME(U)&",KNOWN VERTEX:"&PRINTNAME(K) EOM;
wait;
end;
END;
INTERNAL REAL PROCEDURE DOT_PROD(SAFE REAL ARRAY V1,V2);
COMMENT VALUE IS THE DOT PRODUCT OV VECTORS V1 AND V2.;
BEGIN REAL DP;
INTEGER I;
DP←0.0;
FOR I←1 STEP 1 UNTIL 3 DO DP←DP+V1[I]*V2[I];
RETURN (DP);
END;
INTERNAL REAL PROCEDURE ANGLE(SAFE REAL ARRAY ITEMVAR P1,P2,P3);
COMMENT RETURNS THE ANGLE IN DEGREES OF THE ANGLE FORMED BY P1,P2,P3;
BEGIN
SAFE OWN REAL ARRAY V1,V2[1:3];
INTEGER I;
REAL MSV1,MSV2,X,DOT;
DOT←MSV1←MSV2←0.0;
FOR I←1 S1U 3 DO
BEGIN
V1[I]←DATUM(P1)[I]-DATUM(P2)[I];
V2[I]←DATUM(P3)[I]-DATUM(P2)[I];
DOT←DOT+V1[I]*V2[I];
MSV1←MSV1+V1[I]↑2;
MSV2←MSV2+V2[I]↑2;
END;
X←DOT/SQRT(MSV1*MSV2);
IF ABS(X)>1.0
THEN BEGIN
TYPE "SIMPLE - ANGLE COMPLAINING THAT "&CVG(X)&" IS GREATER THAN 1.0" EOM;
X←IF X<0.0 THEN -1.0 ELSE 1.0;
END;
X←57.3*ACOS(X);
RETURN(X);
END;
INTERNAL BOOLEAN PROCEDURE PARALLEL(ITEMVAR E1,E2);
BEGIN
REAL PROCEDURE SLOPE(ITEMVAR L);
BEGIN
SAFE REAL ARRAY ITEMVAR P1,P2;
SET S;
REAL M;
S←(ENDPT⊗L);
P1←LOP(S);
P2←COP(S);
M←(DATUM(P2)[6]-DATUM(P1)[6])/(DATUM(P2)[5]-DATUM(P1)[5]);
IF DEB_SIMP THEN
BEGIN
TYPE PRINTNAME(P1)&" "&PRINTNAME(P2) EOM; WAIT;
TYPE "SLOPE= "&CVG(M) EOM;
END;
RETURN (M);
END;
REAL T1,T2;
T1←57.3*ATAN(SLOPE(E1));
T2←57.3*ATAN(SLOPE(E2));
IF DEB_SIMP THEN
BEGIN
TYPE "CALL TO PARALLEL: T1-T2= "&CVG(T1-T2) EOM;
WAIT;
END;
IF ABS(T1-T2)<10.0 THEN RETURN (TRUE) ELSE RETURN (FALSE);
END;
INTERNAL PROCEDURE VERT0;
BEGIN LABEL L1,L2;
ITEMVAR E1,E2,E3,E4;
X←HIGHEST(SVS);
S1←(ENDPT`X);
E1←LOP(S1);
E2←COP(S1);
ASSIGN E3|E3εSES AND (E3≠E1) AND (E3≠E2) AND ADJ(E3,E1) HOLDS;
ASSIGN E4| E4εSES AND (E4≠E2) AND (E4≠E1) AND ADJ(E4,E2) HOLDS;
IF VERT0F>0 THEN GOTO L1 ELSE IF VERT0F<0 THEN GOTO L2;
IF ABS(LENTH(E3)-LENTH(E4))<0.4 THEN
L1:BEGIN
IF DEB_SIMP THEN
BEGIN
TYPE "CALL TO VERT0: E3 AND E4 PARALLEL." EOM;
WAIT;
END;
V1←X;
ASSIGN V2| ENDPT⊗E1≡V2 AND ENDPT⊗E3≡V2 HOLDS;
V3←NEXTV(V1,V2);
V4←NEXTV(V2,V3);
ASSIGN B| ENDPT⊗E2≡B AND ENDPT⊗E4≡B HOLDS;
VERT_PLANE_PT(V1,V2,B);
VERT0F← -1; RETURN;
END ELSE L2:BEGIN
IF DEB_SIMP THEN
BEGIN
TYPE "CALL TO VERT0: E3 AND E4 NOT PARALLEL." EOM;
WAIT;
END;
S1←SVS;
REMOVE X FROM S1;
V1←HIGHEST(S1);
V2←NEXTV(X,V1);
V3←NEXTV(V1,V2);
V4←NEXTV(V2,V3);
VERT_PLANE_PT(V1,V2,V3);
VERT0F←1;
END;
END;
INTERNAL PROCEDURE VERT1;
BEGIN
FOREACH Y|YεVERTEDG DO
BEGIN
S1←(ENDPT⊗Y);
V1←LOP(S1);
V2←COP(S1);
IF DATUM(V1)[6]>DATUM(V2)[6] THEN
BEGIN X←V2; V2←V1; V1←X; END;
V3←NEXTV(V1,V2);
V4←NEXTV(V2,V3);
VERT_LINE_PT(V1,V2);
COMMENT horiz_plane_pt(v3,v2);
COMMENT horiz_plane_pt(v4,v2);
IF SPECIAL_VERT THEN BEGIN
V4←V3; V3←V2; V2←V1; V1←NEXTV(V3,V2);
HORIZ_PLANE_PT (V1,V2);
IF DEB_SIMP THEN BEGIN
TYPE "SPECIAL TWO-VERTICAL CASE" EOM;
WAIT; END;
END;
RETURN;
END;
END;
INTERNAL PROCEDURE VERT2;
BEGIN
X←LOWEST(SVS);
S1←(ENDPT`X)∩ VERTEDG;
BVERT←FALSE;
IF S1=PHI THEN BEGIN VERT1; RETURN END;
V1←HIGHEST(SVS);
S1←SVS-{V1⎇;
V2←HIGHEST(S1);
V3←NEXTV(V1,V2);
V4←NEXTV(V2,V3);
VERT_LINE_PT(V2,V3);
HORIZ_PLANE_PT(V1,V2);
END;
END "AUXILIARY SIMPLE PROCEDURES";